


import { engine } from "../../engine/engine";
import { BehaviorTree } from "./BehaviorTree";
import { BehaviorTreeJson, BehaviorTreeRoot } from "./BehaviorTreeDefine";
import { BaseBehaviorNode } from "./base/BaseBehaviorNode";
import { BaseCondition } from "./base/BaseCondition";
import { BaseDecorator } from "./base/BaseDecorator";
import { IBehaviour } from "./interface/IBehaviour";

export class BehaviorTreeBuilderWithJson  {
    private static ins: BehaviorTreeBuilderWithJson;
    static instance(): BehaviorTreeBuilderWithJson {
        if (!this.ins) {
            this.ins = new BehaviorTreeBuilderWithJson()
        }
        return this.ins;
    }
    //操作对象
    private target: any = null;
    //树根
    private root: any = null;

    public buildTree(treeJson: BehaviorTreeJson, target: any = null): BehaviorTree {
        this.target = target;
        let RootClass: any = engine.getClassByName(treeJson.root.type);
        if (RootClass) {
            let treeRoot: IBehaviour = new RootClass();
            treeRoot.setConfig(treeJson, this.target);
            this.addBehaviour(treeRoot, treeJson.root);
            let behaviorTree: BehaviorTree = new BehaviorTree(treeRoot);
            return behaviorTree;
        } else {
            engine.error("rootClass not found! className =", treeJson.root.type);
            return null;
        }
    }
    public buildTreeByName(className: string, treeJson: BehaviorTreeJson, target: any = 0): BehaviorTree {
        this.target = target;
        let RootClass: any = engine.getClassByName(treeJson.root.type);
        if (RootClass) {

            let ClassType: any = engine.getClassByName(className)
            let tree: BehaviorTree = null;
            if (ClassType) {
                tree = new ClassType();
            } else {
                tree = new BehaviorTree();
            }
            this.root = tree;
            // tree.target = target;
            let treeRoot: IBehaviour = new RootClass();
            treeRoot.setConfig(treeJson, this.target);
            this.addBehaviour(treeRoot, treeJson.root);
            tree.root = treeRoot;
            return tree;
        } else {
            engine.error("rootClass not found! className =", treeJson.root.type);
            return null;
        }
    }
    public addBehaviour(behaviourParent: IBehaviour, behaviourData: BehaviorTreeRoot): void {
        if (!behaviourData.children) {
            return;
        }
        for (let i = 0; i < behaviourData.children.length; i++) {
            let config = behaviourData.children[i];
            let BehaviourClass: any = engine.getClassByName(config.type);
            if (BehaviourClass) {
                let behaviour: IBehaviour = new BehaviourClass(behaviourParent);
                // if(behaviour instanceof BaseCondition && child.isNegation){
                //     behaviour.setNegation(child.isNegation);
                // }
                behaviour.setConfig(config, this.target);

                if (behaviour instanceof BaseBehaviorNode) {
                    this.addBehaviourConditions(behaviour, config.conditions);
                    this.addBehaviourDecorators(behaviour, config.decorators);
                }
                behaviourParent.addChild(behaviour);
                this.addBehaviour(behaviour, config);
            } else {
                engine.error("behaviourClass not found! className =", config.type);
            }
        }
    }

    public addBehaviourConditions(behaviourParent: BaseBehaviorNode, conditions: any) {
        if (!conditions) {
            return;
        }

        for (let i = 0; i < conditions.length; i++) {
            let config = conditions[i];
            let BehaviourClass: any = engine.getClassByName(config.type);
            if (BehaviourClass) {
                let behaviour: BaseCondition = new BehaviourClass(behaviourParent);
                behaviour.setConfig(config, this.target);
                behaviourParent.addCondition(behaviour);
                behaviour.tree = this.root;
            } else {
                engine.error("behaviourClass not found! className =", config.type);
            }
        }
    }

    public addBehaviourDecorators(behaviourParent: BaseBehaviorNode, decorators: any[]) {
        if (!decorators) {
            return;
        }

        for (let i = 0; i < decorators.length; i++) {
            let config = decorators[i];
            let BehaviourClass: any = engine.getClassByName(config.type);
            if (BehaviourClass) {
                let behaviour: BaseDecorator = new BehaviourClass(behaviourParent);
                behaviour.setConfig(config, this.target);
                behaviourParent.addDecorator(behaviour);
                behaviour.tree = this.root;
            } else {
                engine.error("behaviourClass not found! className =", config.type);
            }
        }
    }
}